home *** CD-ROM | disk | FTP | other *** search
Java Source | 1997-06-19 | 18.0 KB | 625 lines |
- package symantec.itools.awt;
-
- import java.awt.Dimension;
- import java.awt.Event;
- import java.awt.Font;
- import java.awt.FontMetrics;
- import java.awt.TextField;
-
- // 01/29/97 TWB Integrated changes from Windows
-
- /**
- * Creates a box in which your user can type text. Text formatting logic is
- * applied to the user input.
- * <p>
- * Use FormattedTextField to
- * <UL>
- * <DT>╖ limit the type of text that can be entered in the text box</DT>
- * <DT>╖ display text captured from the keyboard</DT>
- * <DT>╖ edit a line of text</DT>
- * <DT>╖ post an event based on text input from the keyboard</DT>
- * </UL>
- * To post FormattedTextField events or text to other components, use the
- * Interaction Wizard.
- * <p>
- * If the text box already contains text, the user can select the default text
- * and delete or edit it.
- * <p>
- * Upon input error, FormattedTextField sends an error to the standard output
- * device and reads the next character.
- * <p>
- * FormattedTextField does not support logical AND, OR or XOR constructs and
- * does not interactively prompt the user to retry input upon error. You must
- * write project source code to accomplish these tasks.
- * <p>
- * @version 1.0, Nov 26, 1996
- * @author Symantec
- */
-
- public class FormattedTextField
- extends TextField
- {
- /**
- * Mask place constant, mask char following ESCAPE will be placed into input string.
- */
- public final char ESCAPE = '/';
- /**
- * Mask place constant, input must be a digit char.
- */
- public final char DIGIT = '9';
- /**
- * Mask place constant, input must be a sign (+ or -) char.
- */
- public final char SIGN = '+';
- /**
- * Mask place constant, input must be a digit or sign (+ or -) char.
- */
- public final char DIGIT_OR_SIGN = '-';
- /**
- * Mask place constant, input must be an uppercase alpha char.
- */
- public final char ALPHA_UPPER = 'A';
- /**
- * Mask place constant, input must be a lowercase alpha char.
- */
- public final char ALPHA_LOWER = 'a';
- /**
- * Mask place constant, input must be an alpha char (it will be converted to uppercase).
- */
- public final char ALPHA_TO_UPPER = 'U';
- /**
- * Mask place constant, input must be an alpha char (it will be converted to lowercase).
- */
- public final char ALPHA_TO_LOWER = 'L';
- /**
- * Mask place constant, input must be a digit or an uppercase alpha char.
- */
- public final char ALPHANUMERIC_UPPER = 'X';
- /**
- * Mask place constant, input must be a digit or a lowercase alpha char.
- */
- public final char ALPHANUMERIC_LOWER = 'x';
- /**
- * Mask place constant, input must be a digit or alpha char (it will be converted to uppercase).
- */
- public final char ALPHANUMERIC_TO_UPPER = 'N';
- /**
- * Mask place constant, input must be a digit or alpha char (it will be converted to lowercase).
- */
- public final char ALPHANUMERIC_TO_LOWER = 'n';
- /**
- * Mask place constant, input can be any char.
- */
- public final char ANY = '*';
-
- /**
- * Character constant, the backspace character.
- */
- protected final int BACKSPACE = 8;
- /**
- * Character constant, the enter character.
- */
- protected final int ENTER = 10;
- /**
- * Character constant, the delete character.
- */
- protected final int DEL = 127;
-
- /**
- * True if the field is editable.
- */
- protected boolean editable;
- /**
- * The zero-relative index of the character after the insertion point caret.
- */
- protected int caret;
- /**
- * The character mask used to define legal field input.
- */
- protected String mask;
- /**
- * A string containing all the mask characters except the ones immediately after ESCAPE characters.
- */
- protected String maskStripEscapes;
- /**
- * The length of maskStripEscapes.
- */
- protected int maskStripEscapesLen;
-
- /**
- * Constructs a new FormattedTextField. It can have 256 columns.
- */
- public FormattedTextField() {
- this(256);
- }
-
- /**
- * Constructs a new FormattedTextField with the specified number of columns.
- */
- public FormattedTextField(int i) {
- this("", i);
- }
-
- /**
- * Constructs a new FormattedTextField containing the specified text.
- * It can have 256 columns.
- */
- public FormattedTextField(String s) {
- this(s, 256);
- }
-
- /**
- * Constructs a new FormattedTextField containing the specified text and
- * able to have the specified number of columns.
- */
- public FormattedTextField(String s, int i) {
- super(s, i);
-
- caret = 0;
- }
-
- /**
- * Sets the valid string format mask for this field.
- * @see #getMask
- */
- public void setMask(String mask) {
- this.mask = mask;
- setFillMask();
- maskStripEscapes = stripMaskEscapes();
- maskStripEscapesLen = maskStripEscapes.length();
- }
-
- /**
- * Gets the current valid string format mask.
- * @return the string that defines valid input into this field.
- * @see #setMask
- */
- public String getMask() {
- return mask;
- }
-
- /**
- * Sets the font used in the field.
- * @see #getEditFont
- */
- public void setEditFont(Font f) {
- super.setFont(f);
- invalidate();
- }
-
- /**
- * Gets the font used in the field.
- * @return the font used for editing in this field
- * @see #getEditFont
- */
- public Font getEditFont() {
- return getFont();
- }
-
- /**
- * Takes no action, use setEditFont instead.
- * This is a standard Java AWT method which gets called to change
- * the font used for drawing text in this component.
- * It has been overridden to eliminate it, use setEditFont instead.
- * @param f the new font to use for drawing text
- * @see #setEditFont
- * @see java.awt.Component#getFont
- */
- public void setFont(Font f) {
- }
-
- /**
- * Sets whether the text field is editable.
- * @param f true if the text field is editable, false otherwise
- * @see #getEditable
- */
- public void setEditable(boolean f) {
- editable = f;
-
- super.setEditable(f);
-
- if (editable)
- enable();
- else
- disable();
- }
-
- /**
- * Gets whether the text field is editable.
- * @return true if the text field is editable, false otherwise
- * @see #setEditable
- */
- public boolean getEditable() {
- return editable;
- }
-
- /**
- * Returns the next valid character in the input string.
- * @param s the input string
- * @param start the zero-relative index of the first character to check in
- * the input string
- * @param mc the mask character used to determine which input characaters
- * are valid
- */
- protected int validChar(String s, int start, char mc) {
- int len = s.length();
- for (int i = start; i < len; ++i) {
- char c = s.charAt(i);
- switch (mc) {
-
- case DIGIT :
- if (Character.isDigit(c))
- return i;
- break;
-
- case SIGN :
- if (c == '+' || c == '-')
- return i;
- break;
-
- case DIGIT_OR_SIGN :
- if (Character.isDigit(c) || c == '+' || c == '-')
- return i;
- break;
-
- case ALPHA_UPPER :
- if (Character.isUpperCase(c))
- return i;
- break;
-
- case ALPHA_LOWER :
- if (Character.isLowerCase(c))
- return i;
- break;
-
- case ALPHANUMERIC_UPPER :
- if (Character.isUpperCase(c) || Character.isDigit(c))
- return i;
- break;
-
- case ALPHANUMERIC_LOWER :
- if (Character.isLowerCase(c) || Character.isDigit(c))
- return i;
- break;
-
- case ALPHA_TO_UPPER :
- if (Character.isUpperCase(c) || Character.isLowerCase(c))
- return i;
- break;
-
- case ALPHA_TO_LOWER :
- if (Character.isUpperCase(c) || Character.isLowerCase(c))
- return i;
- break;
-
- case ALPHANUMERIC_TO_UPPER :
- if (Character.isUpperCase(c) || Character.isLowerCase(c) || Character.isDigit(c))
- return i;
- break;
-
- case ALPHANUMERIC_TO_LOWER :
- if (Character.isUpperCase(c) || Character.isLowerCase(c) || Character.isDigit(c))
- return i;
- break;
-
- case ANY :
- return i;
-
- }
- }
-
- return -1;
- }
-
- /**
- * Sets the text field's contents to be an input template. The mask ESCAPE
- * characters will be place in the field. All other mask characters will
- * have a space in place of them. For example, a mask of "99/-9/-9" results
- * in the text field getting set to " - - ".
- */
- protected void setFillMask() {
- int ml = mask.length();
- int mi = 0;
- String ns = "";
-
- while (mi < ml) {
- char mc = mask.charAt(mi++);
- ns += mc == ESCAPE ? mask.charAt(mi++) : ' ';
- }
-
- setText(ns);
- }
-
- /**
- * Returns a formatted string, given an input string and the current valid
- * character format mask.
- * @param s the input string
- * @return the input string formatted using the current valid character
- * format mask.
- */
- protected String applyMask(String s) {
- boolean fill = false;
- int len = mask.length();
- int mi = 0;
- int si = 0;
- String ns = "";
-
- while (mi < len) {
- char mc = mask.charAt(mi++);
-
- if (mc != ESCAPE) {
- if (!fill) {
- si = validChar(s, si, mc);
- if (si < 0) {
- fill = true;
- ns += ' ';
- continue;
- }
-
- char sc = s.charAt(si++);
-
- switch (mc) {
-
- case ALPHA_TO_UPPER :
- if (Character.isLowerCase(sc))
- sc = Character.toUpperCase(sc);
- break;
-
- case ALPHA_TO_LOWER :
- if (Character.isUpperCase(sc))
- sc = Character.toLowerCase(sc);
- break;
-
- case ALPHANUMERIC_TO_UPPER :
- if (Character.isLowerCase(sc))
- sc = Character.toUpperCase(sc);
- break;
-
- case ALPHANUMERIC_TO_LOWER :
- if (Character.isUpperCase(sc))
- sc = Character.toLowerCase(sc);
- break;
-
- }
-
- ns += String.valueOf(sc);
-
- } else
- ns += ' ';
- } else
- ns += mask.charAt(mi++);
- }
-
- return ns;
- }
-
- private boolean isEscape(int index) {
- return (index < 0 || index >= maskStripEscapesLen) ? false : (maskStripEscapes.charAt(index) == ESCAPE);
- }
-
- private String stripMaskEscapes() {
- int ml = mask.length();
- int mi = 0;
- String nm = "";
-
- while (mi < ml) {
- char mc = mask.charAt(mi++);
- if (mc == ESCAPE)
- ++mi;
- nm += mc;
- }
-
- return nm;
- }
-
- /**
- * Strips escape characters from the given string.
- * For example, a mask of "99/-9/-9" and an input string of "12-3-4"
- * results in "1234".
- * @param s the input string
- * @return the input string stripped of mask escape characters.
- */
- protected String stripMask(String s) {
- int sl = s.length();
- int i = 0;
- String ns = "";
-
- while (i < maskStripEscapesLen && i < sl)
- if (isEscape(i))
- ++i;
- else
- ns += s.charAt(i++);
-
- return ns;
- }
-
- private boolean processChar(int key) {
- int selStart = getSelectionStart();
- int selEnd = getSelectionEnd();
- boolean bs = key == BACKSPACE;
- boolean del = key == DEL;
-
- boolean isSelection = selStart != selEnd;
-
- if (!isSelection) {
- if (bs)
- selStart = selEnd - 1;
- else if (del)
- selEnd = selStart + 1;
- }
-
- int i = bs || del || isSelection ? selStart : selEnd;
-
- if (i < 0)
- i = 0;
-
- boolean wasInEscape = isEscape(i > 0 ? i : 0);
- boolean wasAtEscape = isEscape(bs || del ? (i > 0 ? i - 1 : 0) : i + 1);
-
- boolean inEscapeAtStart;
- if (wasInEscape) {
- inEscapeAtStart = true;
- int j = i;
- while (j >= 0)
- if (!isEscape(j--)) {
- inEscapeAtStart = false;
- break;
- }
-
- if (inEscapeAtStart)
- while (i < maskStripEscapesLen && isEscape(i++)) {}
-
- } else
- inEscapeAtStart = false;
-
- // (for selection processing, should use a startSelAdj and endSelAdj)
- int selAdj = 0;
-
- while (i >= 0)
- if (isEscape(i--))
- ++selAdj;
-
- if (!inEscapeAtStart && wasInEscape && !bs && !del)
- --selAdj;
-
- selStart -= selAdj; // (not necessarily correct if start < escape < end)
- selEnd -= selAdj;
-
- if (selStart < 0)
- selStart = 0;
-
- if (selEnd < 0)
- selEnd = 0;
-
- String s = stripMask(getText());
- int sl = s.length();
-
- String k = bs || del ? "" : String.valueOf((char)key);
- String l = selStart > 0 ? s.substring(0, selStart) : "";
- String r = selEnd < sl ? s.substring(selEnd) : "";
- String es = bs || del ? l + r : l + k + r;
- String ns = applyMask(es);
-
- if (bs || del || !s.equals(stripMask(ns))) {
- setText(ns);
-
- if (bs || del) {
- --selAdj;
-
- caret = selStart + selAdj;
-
- if (wasAtEscape && caret > 0 && isEscape(caret)) {
- i = caret;
- while (i >= 0)
- if (isEscape(i--))
- --caret;
- else
- break;
- }
-
- } else {
- caret = (isSelection ? selStart : selEnd) + selAdj;
-
- if (caret < sl && isEscape(caret + 1)) {
- i = caret + 1;
- while (i < sl)
- if (isEscape(i++))
- ++caret;
- else
- break;
- }
-
- }
-
- select(caret + 1, caret + 1);
- }
-
- return true;
- }
-
- private void processKeyAction(int key) {
- switch (key) {
-
- case Event.LEFT :
- if (--caret < 0)
- caret = 0;
- break;
-
- case Event.RIGHT :
- if (++caret >= maskStripEscapesLen)
- caret = maskStripEscapesLen;
- break;
-
- case Event.HOME :
- caret = 0;
- break;
-
- case Event.END :
- caret = maskStripEscapesLen;
- break;
-
- }
- }
-
- /**
- * Processes KEY_PRESS and KEY_ACTION events.
- * This is a standard Java AWT method which gets called by the AWT
- * method handleEvent() in response to receiving a KEY_PRESS or
- * KEY_ACTION event. These events occur when this component has the focus
- * and the user presses a "normal" or an "action" (F1, page up, etc) key.
- *
- * @param evt the Event
- * @param key the key that was pressed
- * @return true if the event was handled
- * @see java.awt.Component#keyUp
- * @see java.awt.Component#handleEvent
- */
- public boolean keyDown(Event evt, int key) {
- //if the key was tab, pass up the chain
- if(key == 9) return super.keyDown(evt, key);
-
- switch (evt.id) {
-
- case Event.KEY_PRESS :
- if (key != ENTER)
- return processChar(key);
- break;
-
- case Event.KEY_ACTION :
- processKeyAction(evt.key);
- break;
-
- }
-
- return super.keyDown(evt, key);
- }
-
- /**
- * Returns the recommended dimensions to properly display this component.
- * This is a standard Java AWT method which gets called to determine
- * the recommended size of this component.
- *
- * @see #minimumSize
- */
- public Dimension preferredSize() {
- Font f = getFont();
- if (f != null) {
- FontMetrics fm = getFontMetrics(f);
- return new Dimension(fm.stringWidth("ABCDE") + 4, fm.getHeight() + 4);
- }
- return new Dimension(30, 15);
- }
-
- /**
- * Returns the minimum dimensions to properly display this component.
- * This is a standard Java AWT method which gets called to determine
- * the minimum size of this component.
- *
- * @see #preferredSize
- */
- public Dimension minimumSize() {
- return preferredSize();
- }
- }
-
-